package com.ea.admin.service.impl;

import com.ea.admin.service.ChartGenerationService;
import com.ea.admin.service.PDFGenerationService;
import com.ea.admin.service.ReportFileService;
import com.ea.admin.service.ReportService;
import com.ea.common.report.pojo.vo.ReportDetailInfoVo;
import com.ea.common.report.pojo.vo.ReportPropertiesVo;
import com.ea.common.result.BizException;
import com.ea.common.result.ErrorCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;

/**
 * PDF报告生成服务实现类
 * @author luxl
 * date:2025-06-20
 */
@Service
public class PDFGenerationServiceImpl implements PDFGenerationService {

    private static final Logger logger = LoggerFactory.getLogger(PDFGenerationServiceImpl.class);

    @Resource
    private ReportService reportService;
    
    @Resource
    private ReportFileService reportFileService;
    
    @Resource
    private ChartGenerationService chartGenerationService;
    
    @Resource
    private ObjectMapper objectMapper;


    @Override
    public void generateAndOutputPDF(Long accountId,Long reportId, HttpServletResponse response) {
        try {
            // 获取报告详细数据
            ReportDetailInfoVo reportData = reportService.getReportDetail(accountId ,reportId);
            if (reportData == null) {
                throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_REPORT_NOT_EXISTS);
            }

            // 生成PDF
            byte[] pdfBytes = generatePDFFromData(reportData);

            // 设置响应头
            String fileName = reportData.getName() + reportData.getEmoAnalyDate();
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
            response.setContentLength(pdfBytes.length);

            // 直接输出PDF到响应流
            try (OutputStream out = response.getOutputStream()) {
                out.write(pdfBytes);
                out.flush();
            }

        } catch (feign.FeignException.InternalServerError e) {
            logger.error("Feign调用失败: {}", e.getMessage());
            handlePdfError(response, new BizException(ErrorCode.TPS_FEIGN_CONNECTION_ERROR));
            return;
        } catch (feign.FeignException e) {
            logger.error("Feign调用异常: {}", e.getMessage());
            handlePdfError(response, new BizException(ErrorCode.TPS_FEIGN_ERROR));
            return;
        } catch (BizException e) {
            logger.error("业务异常: {}", e.getMessage());
            handlePdfError(response, e);
            return;
        } catch (Exception e) {
            logger.error("生成PDF失败", e);
            handlePdfError(response, new BizException(ErrorCode.SYSTEM_ERROR_PDF_GENERATION_ERROR));
            return;
        }
    }

    /**
     * 处理PDF生成错误响应
     */
    private void handlePdfError(HttpServletResponse response, BizException e) {
        try {
            response.setContentType("application/json;charset=UTF-8");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("msg", e.getMessage());
            errorResponse.put("code", e.getErrorCode().getCode());
            errorResponse.put("success", false);

            ObjectMapper mapper = new ObjectMapper();
            response.getWriter().write(mapper.writeValueAsString(errorResponse));
        } catch (Exception exception) {
            logger.error("处理PDF错误响应失败", exception);
        }
    }

    @Override
    public byte[] generatePDFFromData(ReportDetailInfoVo reportData) {
        try {
            // 准备模板
            String templatePath = "Resources4PDFGeneration/ReportTemplate.jasper";

            ClassPathResource resource = new ClassPathResource(templatePath);
            if (!resource.exists()) {
                throw new BizException(ErrorCode.SYSTEM_ERROR_PDF_TEMPLATE_NOT_FOUND);
            }
            InputStream inputStream = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(inputStream);


            // 准备数据源
            List<Map<String, Object>> dataList = prepareDataSource(reportData);
            if (dataList == null || dataList.isEmpty()) {
                throw new BizException(ErrorCode.SYSTEM_ERROR_PDF_DATA_INVALID);
            }

            // 准备参数
            Map<String, Object> parameters = prepareAllParameters(reportData,dataList );

            // 创建数据源
            JRDataSource dataSource = new JRBeanCollectionDataSource(dataList);

            // 生成PDF
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);

            // 导出为PDF字节数组
            return JasperExportManager.exportReportToPdf(jasperPrint);

        } catch (BizException e) {
            logger.error("从数据生成PDF失败: {}", e.getMessage());
            throw e;
        } catch (JRException e) {
            logger.error("JasperReports处理失败", e);
            throw new BizException(ErrorCode.SYSTEM_ERROR_PDF_EXPORT_ERROR);
        } catch (Exception e) {
            logger.error("从数据生成PDF失败", e);
            throw new BizException(ErrorCode.SYSTEM_ERROR_PDF_GENERATION_ERROR);
        }
    }

    /**
     * 准备所有JasperReports参数
     */
    private Map<String, Object> prepareAllParameters(ReportDetailInfoVo reportData, List<Map<String, Object>> dataList) {
        Map<String, Object> parameters = new HashMap<>();

        // 封面
        prepareCover(parameters);

        // 个人基本信息
        prepareBasicInfo(parameters, reportData);
        
        // 头像图片
        preparePhotoImage(parameters, reportData);

        // 心理检查数据表
        prepareTableDataSources(parameters, reportData);

        // 预警信息
        prepareWarningInfo(parameters, reportData);

        // 情绪分布图数据
        prepareEmotionDistributionChart(parameters, reportData);

        // 个人性格倾向图数据
        preparePersonalityChart(parameters, reportData);

        // 频谱图数据
        prepareSpectrumData(parameters, reportData);
        
        // 代谢图数据
        prepareMetabolismData(parameters, reportData);

        // 个人心理常模图数据
        preparePersonalRadarChart(parameters, reportData);

        // 群体心理常模图数据
        prepareGroupRadarChart(parameters, reportData);

        // 检查建议
        prepareComments(parameters, reportData);

        return parameters;
    }

    /**
     * 准备封面参数
     */
    private void prepareCover(Map<String, Object> parameters) {
        // 设置封面参数
        String coverPath = "Resources4PDFGeneration/cover.jpg";
        ClassPathResource resource = new ClassPathResource(coverPath);
        if (!resource.exists()) {
            logger.warn("封面图片不存在: {}", coverPath);
            parameters.put("cover", "");
        } else {
            try (InputStream inputStream = resource.getInputStream()) {
                byte[] imageBytes = FileCopyUtils.copyToByteArray(inputStream);
                String coverBase64 = Base64.getEncoder().encodeToString(imageBytes);
                parameters.put("cover", coverBase64);
            } catch (IOException e) {
                logger.error("读取封面图片失败: {}", e.getMessage());
                parameters.put("cover", "");
            }
        }
    }

    /**
     * 准备基本信息参数
     */
    private void prepareBasicInfo(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        parameters.put("name", reportData.getName());
        parameters.put("age", reportData.getAge());
        parameters.put("sex", reportData.getSex());
        parameters.put("companyName", reportData.getCompanyName());
        parameters.put("deptName", reportData.getDeptName());
        parameters.put("positionName", reportData.getPositionName());
        parameters.put("emoAnalyDate", reportData.getEmoAnalyDate());
    }
    
    /**
     * 准备头像图片
     */
    private void preparePhotoImage(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        try {
            if (reportData.getPhotoMd5() != null && !reportData.getPhotoMd5().trim().isEmpty()) {
                String photoBase64 = reportFileService.getImageAsBase64(reportData.getPhotoMd5());
                parameters.put("photo", photoBase64 != null ? photoBase64 : "");
            } else {
                parameters.put("photo", "");
            }
        } catch (BizException e) {
            logger.warn("获取头像失败: {}", e.getMessage());
            parameters.put("photo", "");
        } catch (Exception e) {
            logger.warn("获取头像失败", e);
            parameters.put("photo", "");
        }
    }

    /**
     * 心理检查数据表
     */
    private void prepareTableDataSources(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        List<Map<String, Object>> leftTableData = new ArrayList<>();
        List<Map<String, Object>> rightTableData = new ArrayList<>();

        // 即便没有数据也要保证表头完整
        // 左表数据项名称
        String[] leftNames = {"躁郁指数", "身体能量", "强迫指数", "平衡能力", "自信能力", "情绪分裂"};
        // 右表数据项名称
        String[] rightNames = {"焦虑指数", "抑郁指数", "应对能力", "应激反应", "调节能力", "愉悦程度"};

        // 获取报告详细数据
        List<ReportPropertiesVo> items = null;
        if (reportData.getReportDetail() != null && reportData.getReportDetail().getItems() != null) {
            items = reportData.getReportDetail().getItems();
        }

        // 处理左表数据
        for (String itemName : leftNames) {
            Map<String, Object> row = new HashMap<>();
            ReportPropertiesVo item = null;

            if (items != null) {
                item = findItemByName(items, itemName);
            }

            if (item != null) {
                row.put("name", itemName);
                row.put("value", item.getValue() != null ? item.getValue() : "");
                row.put("reference", formatReference(item.getReferenceLower(), item.getReferenceUpper()));
                row.put("res", getComparisonText(item.getCompare()));
            } else {
                // 如果找不到对应数据项，填入空值但保留名称
                row.put("name", itemName);
                row.put("value", "");
                row.put("reference", "");
                row.put("res", "");
            }
            leftTableData.add(row);
        }

        // 处理右表数据
        for (String itemName : rightNames) {
            Map<String, Object> row = new HashMap<>();
            ReportPropertiesVo item = null;

            if (items != null) {
                item = findItemByName(items, itemName);
            }

            if (item != null) {
                row.put("name", itemName);
                row.put("value", item.getValue() != null ? item.getValue() : "");
                row.put("reference", formatReference(item.getReferenceLower(), item.getReferenceUpper()));
                row.put("res", getComparisonText(item.getCompare()));
            } else {
                // 如果找不到对应数据项，填入空值但保留名称
                row.put("name", itemName);
                row.put("value", "");
                row.put("reference", "");
                row.put("res", "");
            }
            rightTableData.add(row);
        }

        // 设置表格数据源参数
        parameters.put("LEFT_TABLE_DATA", new JRBeanCollectionDataSource(leftTableData));
        parameters.put("RIGHT_TABLE_DATA", new JRBeanCollectionDataSource(rightTableData));
    }


    /**
     * 准备预警信息
     */
    private void prepareWarningInfo(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        parameters.put("responseWarningCount", reportData.getResponseWarningCount());
        parameters.put("adaptiveWarningCount", reportData.getAdaptiveWarningCount());
        parameters.put("riskWarningCount", reportData.getRiskWarningCount());
    }

    /**
     * 准备情绪分布图数据
     */
    private void prepareEmotionDistributionChart(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        if (reportData.getReportDetail() == null || reportData.getReportDetail().getItems() == null) {
            parameters.put("emoGraph", "");
            return;
        }
        // 生成情绪分布图
        String chartBase64 = chartGenerationService.generateEmotionDistributionChart(reportData.getReportDetail().getItems());
        parameters.put("emoGraph", chartBase64 != null ? chartBase64 : "");
    }


    /**
     * 准备个人性格倾向图数据
     */
    private void preparePersonalityChart(Map<String, Object> parameters, ReportDetailInfoVo reportData){
        if (reportData.getReportDetail() == null || reportData.getReportDetail().getItems() == null) {
            parameters.put("characterGraph", "");
            return;
        }

        // 获取外向性和稳定性
        int extraversion = reportData.getReportDetail().getItems().get(19) != null ? Integer.parseInt(reportData.getReportDetail().getItems().get(19).getValue()) : 0;
        int stability = reportData.getReportDetail().getItems().get(20)  != null ? Integer.parseInt(reportData.getReportDetail().getItems().get(20).getValue()) : 0;

        // 生成性格倾向图
        String chartBase64 = chartGenerationService.generatePersonalityChart(extraversion, stability);
        parameters.put("characterGraph", chartBase64 != null ? chartBase64 : "");
    }




    /**
     * 准备频谱图数据
     */
    private void prepareSpectrumData(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        if (reportData.getReportDetail() == null) {
            return;
        }

        // 准备图表
        if(reportData.getReportDetail().getMentalSpectrum() == null){
            parameters.put("psySpectrogram", "");
        }else {
            String chartBase64 = chartGenerationService.generateSpectrumChart(reportData.getReportDetail().getMentalSpectrum());
            parameters.put("psySpectrogram", chartBase64 != null ? chartBase64 : "");
        }
        // 平均频率
        ReportPropertiesVo avgFreq = findItemByName(reportData.getReportDetail().getItems(), "平均频率");
        if (avgFreq != null && avgFreq.getValue() != null) {
            try {
                double value = Double.parseDouble(avgFreq.getValue()) / 1000;
                DecimalFormat df = new DecimalFormat("0.000");
                parameters.put("averageFrequency", df.format(value));
            } catch (NumberFormatException e) {
                logger.warn("平均频率值格式错误: {}", avgFreq.getValue());
                parameters.put("averageFrequency", "0.000");
            }
        } else {
            parameters.put("averageFrequency", "0.000");
        }
        // 稳定性
        ReportPropertiesVo stability = findItemByName(reportData.getReportDetail().getItems(), "稳定性");
        parameters.put("stability", stability != null ? stability.getValue() + "%" : 0);
    }
    
    /**
     * 准备代谢图数据
     */
    private void prepareMetabolismData(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        if (reportData.getReportDetail() == null) {
            return;
        }

        // 准备图表
        if(reportData.getReportDetail().getMentalRateVo() == null || reportData.getReportDetail().getMentalRateVo().getFront() == null){
            parameters.put("mentalRateG", "");
        }else {
            String chartBase64 = chartGenerationService.generateMetabolismChart(reportData.getReportDetail().getMentalRateVo().getFront());
            parameters.put("mentalRateG", chartBase64 != null ? chartBase64 : "");
        }


        DecimalFormat df = new DecimalFormat("#.##");
        // 心理变化（mentalMin ~ mentalMax）
        Object mentalMin = reportData.getReportDetail().getMentalMin();
        Object mentalMax = reportData.getReportDetail().getMentalMax();
        if (mentalMin != null && mentalMax != null) {

            parameters.put("mentalChanges", df.format(mentalMin) + "~" + df.format(mentalMax));
        } else {
            parameters.put("mentalChanges", "未知");
        }
        
        // 心理代谢
        Object mentalAvg = reportData.getReportDetail().getMentalAverage();
        if (mentalAvg != null) {
            parameters.put("mentalAvg", df.format(mentalAvg) + "kcal/min");
        } else {
            parameters.put("mentalAvg", "0.00kcal/min");
        }
    }

    /**
     * 准备群体心理常模图数据
     */
    private void preparePersonalRadarChart(Map<String, Object> parameters, ReportDetailInfoVo reportData){
        if (reportData.getReportDetail() == null || reportData.getReportDetail().getPersonalNorm() == null) {
            parameters.put("personalNormG", "");
            return;
        }

        // 生成个人心理常模对比雷达图
        String chartBase64 = chartGenerationService.generateRadarChart(reportData.getReportDetail().getPersonalNorm(),true);
        parameters.put("personalNormG", chartBase64 != null ? chartBase64 : "");
    }

    /**
     * 准备群体心理常模图数据
     */
    private void prepareGroupRadarChart(Map<String, Object> parameters, ReportDetailInfoVo reportData){
        if (reportData.getReportDetail() == null || reportData.getReportDetail().getGroupNorm() == null) {
            parameters.put("groupNormG", "");
            return;
        }
        // 生成群体心理常模对比雷达图
        String chartBase64 = chartGenerationService.generateRadarChart(reportData.getReportDetail().getGroupNorm(),false);
        parameters.put("groupNormG", chartBase64 != null ? chartBase64 : "");
    }

    /**
     * 准备检查建议
     */
    private void prepareComments(Map<String, Object> parameters, ReportDetailInfoVo reportData) {
        if (reportData.getReportDetail() != null && reportData.getReportDetail().getComment() != null) {
            String comment = reportData.getReportDetail().getComment();
            // 按分号分割并添加编号
            String[] parts = comment.split("；");
            StringBuilder formattedComment = new StringBuilder();
            for (int i = 0; i < parts.length; i++) {
                if (!parts[i].trim().isEmpty()) {
                    formattedComment.append(i + 1).append(". ").append(parts[i].trim());
                    if (i < parts.length - 1) {
                        formattedComment.append("\n");
                    }
                }
            }
            parameters.put("comment", formattedComment.toString());
        } else {
            parameters.put("comment", "无");
        }
    }
    
    /**
     * 根据名称查找数据项
     */
    private ReportPropertiesVo findItemByName(List<ReportPropertiesVo> items, String name) {
        if (items == null) {
            return null;
        }
        return items.stream()
                .filter(item -> name.equals(item.getName()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 准备数据源
     */
    private List<Map<String, Object>> prepareDataSource(ReportDetailInfoVo reportData) {
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> emptyRow = new HashMap<>();
        dataList.add(emptyRow);

        return dataList;
    }
    
    /**
     * 格式化参考值范围
     */
    private String formatReference(String lower, String upper) {
        if (lower != null && upper != null) {
            return lower + "~" + upper;
        } else if (lower != null) {
            return ">" + lower;
        } else if (upper != null) {
            return "<" + upper;
        } else {
            return "未知";
        }
    }

    /**
     * 获取比较结果文本
     */
    private String getComparisonText(Integer comparison) {
        if (comparison == null) {
            return "未知";
        }
        switch (comparison) {
            case 0: return "正常";
            case 1: return "偏高";
            case 2: return "偏低";
            default: return "未知";
        }
    }
}